package mn.more.foundation.lang;

import java.util.StringTokenizer;
import org.apache.commons.lang.StringUtils;

// only for JDK 1.4.*
//import java.util.regex.Matcher;

//import java.util.regex.Pattern;
/**
 * general utility for <code>String</code> object manipulations and handling.
 * <p/>
 * Some of the methods are spin-off from Apache Commons; the reason for
 * duplicating them here is to <ol> <li>create further enhancement and, <li>a
 * code-level independence from 3rd party API. </ol>
 * <p/>
 * In case Apache Commons make some drastic changes to its offering, we can
 * localize the changes (and the impact thus) in this class.
 *
 * @author <a href="mailto:mike.liu@aptechmongolia.edu.mn">Mike Liu</a>
 * @version $Id: StringUtil.java 5 2008-09-01 12:08:42Z mikeliucc $
 */
public final class StringUtil {

	// only for JDK 1.4.*
	//public static final Pattern ALL_PUNCTUATION = Pattern.compile("\\p{Punct}");
	private static final String ALL_PUNCTUATION =
		"~`!@#$%^&*()_-=+|}{\":?><,./;'[]\\'";
	private static final String TEMP_REPLACE_TOKEN = "<<<!!!#$%^&*()>>>";

	/** singleton class restricts construction */
	private StringUtil() { }

	/**
	 * (Delegate to Apache Commons) Checks if a (trimmed) String is null or empty.
	 *
	 * @param text string to check
	 * @return true if the String is null, or length zero once trimmed
	 */
	public static boolean isEmpty(String text) {
		return StringUtils.isEmpty(text);
	}

	/** return true if <code>text</code> is whitespaces, "" or null. */
	public static boolean isBlank(String text) {
		return StringUtils.isBlank(text);
	}

	/**
	 * (Delegate to Apache Commons) Replace all occurances of a string within
	 * another string
	 *
	 * @return the replaced string
	 */
	public static String replace(String text, String replace, String with) {
		return StringUtils.replace(text, replace, with);
	}

	public static String replaceFirst(String text,
	                                  String replace,
	                                  String with) {
		return StringUtils.replace(text, replace, with, 1);
	}

	/**
	 * "escape" all punctunation as they are used for special purpose otherwise.
	 *
	 * @return cleaned up text
	 */
	public static String escapePunctuation(String text) {
		// sanity check
		if (text == null) { return null; }
		if (text.length() < 1) { return text; }

		// only for JDK 1.4.*
		//Matcher matcher = ALL_PUNCTUATION.matcher(text);
		//StringBuffer sb = new StringBuffer();
		//while (matcher.find()) {
		//	matcher.appendReplacement(sb, "\\\\");
		//	sb.append(matcher.group());
		//}
		//matcher.appendTail(sb);
		//return sb.toString();

		StringBuilder sb = new StringBuilder(text.length());
		char[] characters = text.toCharArray();
		for (char c : characters) {
			if (ALL_PUNCTUATION.indexOf(c) != -1) {
				sb.append('\\').append(c);
			} else {
				sb.append(c);
			}
		}

		return sb.toString();
	}

	/**
	 * returns <code>text</code> in "TITLE" case format.  Title case format is one
	 * that capitalized the first letter of every word.
	 *
	 * @return <code>text</code> in title-case
	 * @see #toTitleCase(String,String)
	 */
	public static String toTitleCase(String text) {
		return StringUtil.toTitleCase(text, " ");
	}

	/**
	 * returns <code>text</code> in "TITLE" case format.  Title case format is one
	 * that capitalized the first letter of every word.
	 *
	 * @return <code>text</code> in title-case
	 */
	public static String toTitleCase(String text, String wordSeparator) {
		// sanity check
		if (isEmpty(text)) { return ""; }

		// default separator is space.
		if (isEmpty(wordSeparator)) { wordSeparator = " "; }

		// conversion starts here...
		StringBuilder buffer = new StringBuilder(text.length());
		StringTokenizer tokenizer = new StringTokenizer(text, wordSeparator);
		while (tokenizer.hasMoreTokens()) {
			String temp = tokenizer.nextToken();
			buffer.append(temp.substring(0, 1).toUpperCase());

			// if the entire word is upper case, then turn it to lowercase
			String theRestOfThisWord = temp.substring(1);
			if (theRestOfThisWord.toUpperCase().equals(theRestOfThisWord)) {
				buffer.append(theRestOfThisWord.toLowerCase());
			} else {
				// otherwise, keep it as it is.
				buffer.append(theRestOfThisWord);
			}

			if (tokenizer.hasMoreTokens()) {
				buffer.append(wordSeparator);
			}
		}

		// get rid of the last <code>wordSeparator</code> and return
		return buffer.toString().trim();
	}

	/**
	 * create a n length of space
	 *
	 * @return spaces
	 */
	public static String space(int length) { return repeat(" ", length); }

	/**
	 * Repeat a string n times to form a new string.  This implmentation currently
	 * borrows from Jakarta-Commons project.
	 */
	public static String repeat(String str, int length) {
		return StringUtils.repeat(str, length);
	}

	/**
	 * this method will find the <code>repeatStr</code> within
	 * <code>originalText</code> and repeats the <code>repeatStr</code> n times
	 * (depending on <code>numberOfRepeat</code>.
	 */
	public static String repeatWithin(String originalText,
	                                  String repeatStr,
	                                  int numberOfRepeat) {
		String replaceWith = StringUtil.repeat(repeatStr, numberOfRepeat);
		String newText = StringUtil.replace(originalText,
		                                    repeatStr,
		                                    TEMP_REPLACE_TOKEN);
		return StringUtil.replace(newText, TEMP_REPLACE_TOKEN, replaceWith);
	}

	public static String handleSingleQuote(String text) {
		return repeatWithin(text, "'", 2);
	}

	public static String leftPad(String text, String padWith, int totalLength) {
		return StringUtils.leftPad(text, totalLength, padWith);
	}

	public static String rightPad(String text,
	                              String padWith,
	                              int totalLength) {
		return StringUtils.rightPad(text, totalLength, padWith);
	}

	public static String substring(String text, int startIndex, int endIndex) {
		return StringUtils.substring(text, startIndex, endIndex);
	}

	///**
	// * use the <code>values</code> to replace tokens in <code>templates</code>,
	// * thus forming the intended text via substitution.<p>
	// *
	// * The templates should be in the form of:
	// * "text text {0} text {1} text text {2} {3} ...", where
	// * {x} represents the token matching with the index of <code>values</code>
	// * array.
	// *
	// * @param templates
	// * @param values
	// * @return the final substituted string
	// */
	//public static String substitute(String templates, Object[] values) {
	//	// todo-mike: work on this
	//	throw new RuntimeException("not yet implemented.");
	//}

}
